package com.assic.utils.clazz;

import java.io.File;
import java.io.FileNotFoundException;
import java.io.FileOutputStream;
import java.io.PrintWriter;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URLClassLoader;

import com.sun.tools.javac.Main;

/**
 * 动态编译
 * 
 * @author Kerbores
 * 
 */
public class DynamicCompiler {

	/**
	 * eval函数
	 * 
	 * @param info
	 *            输入串
	 * @return 输入串的表达式结果
	 */
	public Object eval(String info) {
		try {
			String className = "Kerbores";
			String classDir = System.getProperty("user.dir");
			File file = new File(classDir, className + ".java");
			PrintWriter out;

			out = new PrintWriter(new FileOutputStream(file));
			// 代码
			StringBuffer sbf = new StringBuffer(128);
			sbf.append("public class ");
			sbf.append(className);
			sbf.append("{");
			sbf.append("public Object eval () {");
			sbf.append("return " + info + ";");
			sbf.append("}");
			sbf.append("}");
			String code = sbf.toString();
			out.println(code);
			out.flush();
			out.close();
			int i = Main.compile(new String[] { "-d", classDir, file.getName() });// 记得要配置JAVA_HOME
			// 而且运行此类需要jdk而不是jre
			// 因为JRE不包含sun包
			// JAVA_HOME/jdk/lib/tools.jar
			URL url = new URL("file://" + classDir + File.separator);
			@SuppressWarnings("resource")
			URLClassLoader loader = new URLClassLoader(new URL[] { url });
			Class<?> clazz = loader.loadClass(className);
			Object obj = clazz.newInstance();
			Method method = clazz.getMethod("eval");
			if (i == 0) {// 判断编译是否包含错误
				return method.invoke(obj);
			}
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		} catch (MalformedURLException e) {
			e.printStackTrace();
		} catch (ClassNotFoundException e) {
			e.printStackTrace();
		} catch (InstantiationException e) {
			e.printStackTrace();
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (NoSuchMethodException e) {
			e.printStackTrace();
		} catch (SecurityException e) {
			e.printStackTrace();
		} catch (IllegalArgumentException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		throw new RuntimeException("'" + info + "' can't be evaled! if '" + info + "' is just a string then you'd surround it with \\\" and \\\"");
	}

}
